/*
Copyright 2007 Raymond Giorgi

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
 */

package edu.pitt.CS2510.Grids;

import java.util.ArrayList;
import java.util.Random;


/**
 * @author Alichino
 *
 * This class represents the 'map' of the simulation. It is composed of a two-dimensional 
 * array of pieces that are either used or unused
 */
public class Grid extends Object {

	private final GridPiece[][] grid;
	private final int height;
	private final int width;
	private ArrayList<GridPiece> enemies = new ArrayList<GridPiece>();
	/**
	 * The constructor that initializes the Grid, which includes instantiating every grid-piece
	 * @param height
	 * @param width
	 */
	public Grid(int height, int width){
		this.height = height;
		this.width = width;
		grid = new GridPiece[height][width];
		for(int i = 0; i < height; i++){
			for(int j = 0; j < width; j++){
				grid[i][j] = new GridPiece(i,j);
			}
		}
	}
	/**
	 * @return a copy of this grid
	 */
	@Override
	public Grid clone(){
		final Grid temp = new Grid(height, width);
		temp.enemies = new ArrayList<GridPiece>(enemies);
		return temp;
	}
	/**
	 * Sets all grid pieces to empty
	 */
	public void clear(){
		for(int i = 0; i < height; i++){
			for(int j = 0; j < width; j++){
				grid[i][j].clear();
			}
		}
	}
	/**
	 * 
	 * @param x
	 * @param y
	 * @return the Gridpiece at location row 'x' and column 'y'
	 */
	public GridPiece getBlock(int x, int y){
		return grid[x][y];
	}
	/**
	 * Randomly populates the grid with enemy pieces. 'enemyUnits' is the number of
	 * enemies to be placed on the grid.
	 * @param enemyUnits
	 */
	public void populateWithEnemies(int enemyUnits){
		for(int i = 0; i < enemyUnits; i++){
			boolean used = true;
			while(used){
				final Random rand = new Random();
				final GridPiece gp = getBlock(rand.nextInt(height - 1) + 1, rand.nextInt(width - 1) + 1);
				if(!gp.isUsed()){
					used = false;
					gp.setUnits(rand.nextInt(39));
					gp.setUsed(true);
					gp.setTeam(0);
					enemies.add(gp);
				}
			}
		}
	}
	/**
	 * 
	 * @param x
	 * @param y
	 * @return returns the population of the gridpiece at row 'x' and column 'y'  
	 */
	public int getUnitsAtBlock(int x, int y){
		return grid[x][y].getUnits();
	}
	/**
	 * 
	 * @param x
	 * @param y
	 * @return true if there are units at row 'x' and column 'y'
	 */
	public boolean isUsedAtBlock(int x, int y){
		return grid[x][y].isUsed();
	}
	/**
	 * Explicitly tell a gridpiece whether it is being used or not.
	 * Technically, this could be done if the piece returned true if 'getUnits()' > 0, but
	 * historical reasons prevents this
	 * @param x
	 * @param y
	 * @param value
	 */
	public void setUsedAtBlock(int x, int y, boolean value){
		grid[x][y].setUsed(value);
	}
	/**
	 * 
	 * @param x
	 * @param y
	 * @return all the gridpieces that are one up, down, left, and right from
	 * row 'x' and column 'y' provided they are not beyond the borders of the grid.
	 */
	public ArrayList<GridPiece> getNeighbors(int x, int y){
		final ArrayList<GridPiece> list = new ArrayList<GridPiece>();

		if(x==0){
			list.add(grid[x+1][y]);
		}else if(x == width -1){
			list.add(grid[x-1][y]);
		}else{
			list.add(grid[x+1][y]);
			list.add(grid[x-1][y]);
		}
		if(y == 0){
			list.add(grid[x][y+1]);
		}else if(y == height - 1){
			list.add(grid[x][y-1]);
		}else{
			list.add(grid[x][y+1]);
			list.add(grid[x][y-1]);
		}
		return list;
	}
//
//	public ArrayList getNeighbors(int x, int y){
//		ArrayList list = new ArrayList();
//		if(x==0){
//			if(isUsedAtBlock(x+1, y)){
//				list.add(getBlock(x+1,y));
//			}
//		}else if(x==width){
//			if(isUsedAtBlock(x-1, y)){
//				list.add(grid[x-1][y]);
//			}
//		}else{
//			if(isUsedAtBlock(x+1,y)){
//				list.add(getBlock(x+1,y));
//			}if(isUsedAtBlock(x-1,y)){
//				list.add(getBlock(x-1,y));
//			}
//		}
//		if(y==0){
//			if(isUsedAtBlock(x,y+1))
//				list.add(getBlock(x,y+1));
//		}else if(y==height){
//			if(isUsedAtBlock(x,y-1))
//				list.add(getBlock(x,y-1));
//		}else{
//			if(isUsedAtBlock(x,y+1))
//				list.add(getBlock(x,y+1));
//			if(isUsedAtBlock(x,y-1))
//				list.add(getBlock(x,y-1));
//		}
//		return list;
//	}
	/**
	 * @return true if there is more than 0 enemy units at a given location 
	 */
	public boolean enemiesRemain(){
		if(enemies.size()>0){
			return true;
		}
		return false;
	}

	public ArrayList<GridPiece> getEnemies(){
		return enemies;
	}

	public void setEnemies(ArrayList<GridPiece> enemies) {
		this.enemies = enemies;
	}

}
